/**
 * OSAmI: Open Source Ambient Intelligence
 * A simple discovery protocol (based on multicast communications) for constrained devices.
 * Copyright (C) Lionel Debroux 2006 (as a TER/Magistere M1 student in the LSR-IMAG-ADELE team, for a demo in the H-Omega project)
 * Copyright (C) Lionel Debroux 2010 (as an engineer in the LCIS-INPG-CTSYS team, for a pre-demo in the FR part of the OSAMI project)
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
 */

package fr.imag.adele.homega.impl.discovery;

import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.UUID;

import fr.imag.adele.homega.impl.multicast.MulticastHandler;
import fr.imag.adele.homega.impl.multicast.MulticastHandlerImpl;
import fr.imag.adele.homega.impl.multicast.MulticastReceiver;
import fr.imag.adele.homega.impl.multicast.MulticastReceiverImpl;

/**
 * This class (surprisingly ?) provides a testcase for the discovery API.
 */
public class DiscoveryTest {

	private static final String DISCOVERY_BRIDGE_ADDRESS = "FF02:0:0:0:0:0:0:99"; //"226.0.0.1";
	private static final int DISCOVERY_BRIDGE_PORT = 0xF0B1; // 10001

	private static final String DISCOVERY_DEVICE1_ADDRESS = "FF02:0:0:0:0:0:0:9A"; //"227.0.0.1";
	private static final int DISCOVERY_DEVICE1_PORT = 0xF0B2; // 10101

	private static final String DISCOVERY_DEVICE2_ADDRESS = "FF02:0:0:0:0:0:0:9B"; //"227.0.0.2";
	private static final int DISCOVERY_DEVICE2_PORT = 0xF0B3; // 10201

	private static final int NAP_TIME = 20;

	public static void main(String[] args) {
		Device device1 = null;
		Device device2 = null;
		String device1ID = null;
		String device2ID = null;
		DeviceEvent event = null;

		DiscoveryBridge bridge = null;

		MulticastReceiver monitor = null;
		MulticastHandler monitorHandler = null;

		try {
			Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).setLevel(Level.ALL);
			System.runFinalizersOnExit(true); // XXX


			// Create bridge first.
			/*System.out.println("=== Creating bridge ===");
			bridge = new DiscoveryBridgeImpl(DISCOVERY_BRIDGE_ADDRESS, DISCOVERY_BRIDGE_PORT, null, null);
		Thread.sleep(NAP_TIME);*/

			// Create monitor (snooper) and register it to all topics.
			System.out.println("=== Creating monitor ===");
			monitorHandler = new MulticastHandlerImpl();
			monitor = new MulticastReceiverImpl("monitor");
			monitor.register(monitorHandler, DISCOVERY_BRIDGE_ADDRESS, DISCOVERY_BRIDGE_PORT);
			monitor.register(monitorHandler, DISCOVERY_DEVICE1_ADDRESS, DISCOVERY_DEVICE1_PORT);
			monitor.register(monitorHandler, DISCOVERY_DEVICE2_ADDRESS, DISCOVERY_DEVICE2_PORT);
		Thread.sleep(NAP_TIME);


			// Create first device.
			System.out.println("=== Creating device 1 ===");
			device1ID = UUID.randomUUID().toString();
			device1 = new DeviceImpl("device1",
					DISCOVERY_BRIDGE_ADDRESS, DISCOVERY_BRIDGE_PORT, // Bridge
					DISCOVERY_DEVICE1_ADDRESS, DISCOVERY_DEVICE1_PORT, // Device
					device1ID);
			
			device1.addMetadata("BridgeURL", "file:///foo");
			device1.addMetadata("Type", "ProviderType1");
		Thread.sleep(NAP_TIME);
		Thread.sleep(5000);

			// Handshake.
			/*System.out.println("=== Probe * ===");
			bridge.probe("*");
		Thread.sleep(NAP_TIME);

			System.out.println("=== Bridge metadata after probe ===");
			System.out.println(bridge.getAllMetadata());
		Thread.sleep(NAP_TIME);*/

			// Create second device.
			System.out.println("=== Creating device 2 ===");
			device2ID = UUID.randomUUID().toString();
			device2 = new DeviceImpl("device2",
					DISCOVERY_BRIDGE_ADDRESS, DISCOVERY_BRIDGE_PORT, // Bridge
					DISCOVERY_DEVICE2_ADDRESS, DISCOVERY_DEVICE2_PORT, // Device
					device2ID);
			device2.addMetadata("BridgeURL", "file:///bar");
			device2.addMetadata("Type", "ProviderType2");
		Thread.sleep(NAP_TIME);

			// Handshake.
			System.out.println("=== Device 2 sending hello ===");
			device2.hello();
		Thread.sleep(NAP_TIME);

			/*System.out.println("=== Bridge metadata after device 2 hello ===");
			System.out.println(bridge.getAllMetadata());
		Thread.sleep(NAP_TIME);

			// Handshake.
			System.out.println("=== Probe specific type, should see a reply from device1 only ===");
			bridge.probe("ProviderType1");
		Thread.sleep(NAP_TIME);

			System.out.println("=== Bridge metadata after probe ===");
			System.out.println(bridge.getAllMetadata());
		Thread.sleep(NAP_TIME);*/


			// Send messages.
			System.out.println("=== Sending messages ===");
			device1.send(DISCOVERY_DEVICE2_ADDRESS, DISCOVERY_DEVICE2_PORT, "Hi from 1 !");
			device2.send(DISCOVERY_DEVICE1_ADDRESS, DISCOVERY_DEVICE1_PORT, "Hi from 2 !");
		Thread.sleep(NAP_TIME);

			// Send events.
			System.out.println("=== Sending events ===");
			event = new DeviceEvent(device1ID);
			event.addInfo("key1","value1");
			event.addInfo("key2","value2");
			event.addInfo("key3","value3");
			event.addInfo("key4","value4");
			device1.sendEvent(event);
		Thread.sleep(NAP_TIME);

			System.out.println("=== Quitting device 1 ===");
			device1.bye();
		Thread.sleep(NAP_TIME);

			/*System.out.println("=== Bridge metadata after device 1 quit ===");
			System.out.println(bridge.getAllMetadata());
		Thread.sleep(NAP_TIME);

			// Handshake.
			System.out.println("=== Probe specific type, should not see any reply as device1 is gone ===");
			bridge.probe("ProviderType1");
		Thread.sleep(NAP_TIME);

			System.out.println("=== Bridge metadata after probe ===");
			System.out.println(bridge.getAllMetadata());
		Thread.sleep(NAP_TIME);*/

			System.out.println("=== Quitting device 2 ===");
			device2.bye();
		Thread.sleep(NAP_TIME);

			/*System.out.println("=== Bridge metadata after device 2 quit ===");
			System.out.println(bridge.getAllMetadata());
		Thread.sleep(NAP_TIME);*/

			System.out.println("=== Over ! ===");
		Thread.sleep(NAP_TIME);

		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			if (device2 != null)        device2.shutdown();
			if (device1 != null)        device1.shutdown();

			if (monitor != null)        monitor.shutdown();
			if (monitorHandler != null) monitorHandler.shutdown();
			if (bridge != null)         bridge.shutdown();
		}
		
	}

}
